/******************************************************************************
 * (C) Copyright 2013 Atech-Automotive
 * FILE NAME:    uds_can_trans.c
 * DESCRIPTION:
 * 
 * DATE BEGUN:   2015/05/05
 * BY:           hui.pang
 * PRODUCT NAME:
 * APPLICATION:
 * TARGET H/W:
 * DOC REF:
 *****************************************************************************
 */

/*****************************************************************************
** #include 
*****************************************************************************/
#include "system.h"
#include "uds_can_trans.h"
#include "uds_can_trans_cfg.h"
//#include "Slave_lin1_appl.h"
//#include "Slave_lin1_apis.h"
#include "uds_diag_drv.h"
#include "uds_diag_interface.h"
#include "uds_diag_callback.h"
#include "string.h"

#pragma CODE_SEG  OTHER_ROM


/*****************************************************************************
** typedef
*****************************************************************************/
/*
** Values for "cantp_status".
*/
typedef enum
{
    TX_RX_IDLE          = 0x00,
    TX_FC_TPDU          = 0x01,  /* =1 when a FC frame needs to be TX'd */
    TX_LAST_FRAME_ERROR = 0x02,  /* =1 when last send frame has error */
    RX_IN_PROGRESS      = 0x20,  /* =1 when RX in progress    */
    TX_WAIT_FC          = 0x40,  /* =1 when awaiting FC frame */
    TX_IN_PROGRESS      = 0x80   /* =1 when TX in progress    */

} Uds_CantpSts_E;

/*
** Frame types arranged in numerical order for efficient switch statement
** jump tables.
*/
typedef enum
{
    TX_SF = 0, /* Single Frame */
    TX_FF,     /* First Frame */
    TX_CF,     /* Consecutive Frame */
    TX_FC      /* Flow Control Frame */

} Uds_FrameType_E;

/*
** Masks for the PCI(Protcol Control Information) byte. 
** The MS bit contains the frame type.
** The LS bit is mapped differently, depending on frame type, as follows:
**  SF: DL (number of diagnostic bytes NOT including the PCI byte; only the
**       3 LS bits are used).
**  FF: XDL (extended data length; always be 0.)
**  CF: Sequence number,4 bits, max value:15.
**  FC: Flow Status. The value of FS shall be set to zero that means that
**      the tester is ready to receive a maximum number of CF.
*/
typedef enum /* Don't change these values, these must be  */
{
    /* MS bits -  Frame Type */
    FRAME_TYPE_MASK  = 0xF0,
    SF_TPDU          = 0x00, /* Single frame                 */
    FF_TPDU          = 0x10, /* First frame                  */
    CF_TPDU          = 0x20, /* Consecutive frame            */
    FC_TPDU          = 0x30, /* Flow control frame           */
    FC_OVFL_PDU      = 0x32, /* Flow control frame           */

    /* LS bits - SF_DL */    
    SF_DL_MAX_BYTES  = 0x07, /* SF Max Data Length */
    SF_DL_MASK       = 0x07, /* number diagnostic data bytes */    
    SF_DL_MASK_LONG  = 0x0F, /* change to check the 4 bits for testing, number diagnostic data bytes */

    /* LS bits - FF_DL */   
    FF_EX_DL_MASK    = 0x0F, /* Extended data length         */

    /* LS bits - CF_SN */
    CF_SN_MASK       = 0x0F, /* Sequence number mask         */
    CF_SN_MAX_VALUE  = 0x0F, /* Max value of sequence number */
    
    /* LS bits - FC Saatus */
    FC_STATUS_CONTINUE   = 0x00, /* Flow control frame, CONTINUE */
    FC_STATUS_WAIT       = 0x01, /* Flow control frame, WAIT */
    FC_STATUS_OVERFLOW   = 0x02, /* Flow control frame, OVERFLOW */
    FC_STATUS_MASK       = 0x0F, 

} Uds_PCI_E;

/* 
** Structure for CAN RX frames.
*/
typedef struct
{
    UINT8 info_byte; /* used by the NOS */
    UINT8 tpci;      /* transport protocol control information */
    UINT8 data1;     /* data byte 1 */ /* BS(Block Size) when FC */
    UINT8 data2;     /* data byte 2 */ /* ST when FC */
    UINT8 data3;     /* data byte 3 */
    UINT8 data4;     /* data byte 4 */
    UINT8 data5;     /* data byte 5 */
    UINT8 data6;     /* data byte 6 */
    UINT8 data7;     /* Data byte 7 */
    
} Uds_RxFrameData_S;

/* 
** Structure for CAN TX frames.
*/
typedef struct
{
    UINT8 tpci;      /* transport protocol control information */
    UINT8 data1;     /* data byte 1 */
    UINT8 data2;     /* data byte 2 */
    UINT8 data3;     /* data byte 3 */
    UINT8 data4;     /* data byte 4 */
    UINT8 data5;     /* data byte 5 */
    UINT8 data6;     /* data byte 6 */
    UINT8 data7;     /* Data byte 7 */
    
} Uds_TxFrameData_S;   

/*
** Information structure that holds pointers to bytes to be transmitted
** when sending a message to the tester.
**    msg_length   = total bytes in the message
**    next_tx_byte = byter number of next byte to be transmitted
**    ptr1         = pointer to first "length1" bytes in message
**    length1      = number of bytes "ptr1" points to
**    ptr2         = pointer to first "length2" bytes in message
**    length2      = number of bytes "ptr2" points to
*/
typedef struct
{
    UINT16 msg_length;
    UINT16 next_tx_byte;
    UINT8  *ptr1;
    UINT16 length1;
    UINT8  *ptr2;
    UINT16 length2;
    UINT8  next_sequence_num;
    
} Uds_TxInfo_S;

/*
** Information structure used to handle multi-frame receive messages.
**  bytes_left_to_rx  = bytes left to receive in message
**  next_sequence_num = next sequence number expected
**  next_rx_offset    = offset into RX buffer where next RX byte is
**  to be placed
*/
typedef struct
{
    UINT16  bytes_left_to_rx;
    UINT8   next_sequence_num;
    UINT16  next_rx_offset;
    
} Uds_RxInfo_S;

/*****************************************************************************
** #define
*****************************************************************************/
#define COMM_STATUS_MASK  ((UINT8)(RX_IN_PROGRESS | TX_IN_PROGRESS | TX_WAIT_FC))


#define BEGINNING_SEQ_NUMBER (1)

/*
** Time to wait for the tester to send a FC frame in response
** to a FF(wait for flow control frame time out).
**  N_As + N_Bs = 25 +75 = 100ms
*/
#define FC_WAIT_TIMEOUT    ((UINT8)(N_As + N_Bs + 50))

/* wait for Consecutive frame time out
** N_Cr < 150ms
*/
#define CF_WAIT_TIMEOUT   ((UINT8)(N_Cr))//(N_Cr - 10))

#define DL   data1
#define BS   data1
#define ST   data2

/*****************************************************************************
** global variable
*****************************************************************************/
BOOL g_cantp_rx_enable = TRUE;

Uds_DiagRxBuffer_S g_cantp_rx_buffer;

Uds_DiagAddrMode_E g_diag_can_address_mode = DIAG_PHYSIC_ADDR_MODE; 

/*****************************************************************************
** static variables
*****************************************************************************/
static Uds_CantpSts_E s_cantp_sts;  
static Uds_RxFrameData_S s_cantp_rx_frame;
static Uds_TxInfo_S s_cantp_tx_info;
static UINT8 s_u8_cf_stmin_time = 0x00;
static UINT8 s_u8_block_size = CLEAR; /* BS(Block Size) in a flow Control Frame */
static UINT8 s_u8_cf_stmin_wait_time = 0x00;  /* STmin Time in Flow Control Frame */
static UINT8 s_u8_fc_wait_time = 0x00; /* Wait for FC when has sent FF */
static BOOL s_b_fc_wait_timeout_disable = FALSE;
static UINT8 s_u8_cf_wait_time = 0x00;
static UINT8 s_u8_cantp_rx_block = 0x00;
static BOOL s_b_over_flow_flag = FALSE;
/**************************************************************************
** static constants
*****************************************************************************/


/*****************************************************************************
** static function prototypes
*****************************************************************************/
static void CanTrans_TxFrame(Uds_FrameType_E frame_type);
static void CanTrans_RxStateAnalyse(void);
//static UINT8 CanTrans_RamCheck( void );

/*****************************************************************************
** function prototypes
*****************************************************************************/


/****************************************************************************/
/****************************************************************************/
/**
 * Function Name: CanTrans_ColdInit
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
void CanTrans_ColdInit( void )
{
    CLEARBIT(s_cantp_sts, (RX_IN_PROGRESS | TX_IN_PROGRESS | TX_FC_TPDU | TX_WAIT_FC | TX_LAST_FRAME_ERROR));
    g_cantp_rx_buffer.info_byte = RX_INFO_INIT;
}

/****************************************************************************/
/**
 * Function Name: CanTrans_Handler1ms
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/07/02, hui.pang create this function
 ****************************************************************************/
void CanTrans_Handler1ms( void )
{
    /* interval of consecutive frame, STmin = 10ms, separation time */
    if ( s_u8_cf_stmin_wait_time > 0 )
    {
        s_u8_cf_stmin_wait_time--;
    }

    /* N_Bs, flow control frame wait time out, 75ms*/
    if ( s_u8_fc_wait_time > 0 )
    {
        s_u8_fc_wait_time--;
        if( 0x00 == s_u8_fc_wait_time )
        {
            s_b_fc_wait_timeout_disable = TRUE;
        }
    }

    /* N_Cr,consecutive frame wait time out, 75ms*/
    if ( s_u8_cf_wait_time > 0 )
    {
        s_u8_cf_wait_time--;
    }
}

#if 0
/****************************************************************************/
/**
 * Function Name: CanTrans_RamCheck
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
static UINT8 CanTrans_RamCheck( void )
{
    /*
    **  Since "cantp_status" is modified in incoming message processing routines,
    **  the following RAM checks should not be performed when incoming message
    **  is processed through the interrupt dispatch.
    */
    if( (s_cantp_sts & COMM_STATUS_MASK) == (RX_IN_PROGRESS | TX_IN_PROGRESS) )
    {
        /*
        ** Can't have RX and TX in progress simultaneously.
        */
        return(FALSE);
    }

    if( (TESTBIT(s_cantp_sts, TX_WAIT_FC)) 
     && (!TESTBIT(s_cantp_sts, TX_IN_PROGRESS))
      )
    {
        /*
        ** Can't be awaiting reciept of FC frame without in TXing state.
        */
        return(FALSE);
    }

    if( (TESTBIT(s_cantp_sts, TX_FC_TPDU)) 
     && (!TESTBIT(s_cantp_sts, RX_IN_PROGRESS))
      )
    {
        /*
        ** Invalid to transmit FC frame if not RXing.
        */
        return(FALSE);
    }

    /*
    ** Enable interrupts when the RAM check is OK.  When RAM check fails,
    ** the program should force a reset to recover.
    */
    return(TRUE);
}
#endif

/****************************************************************************/
/**
 * Function Name: CanTrans_Sleep
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
void CanTrans_Sleep( void )
{ 
    CanTrans_ColdInit();		
}

/*****************************************************************************/
/**
* Function Name: void CanTrans_Wakeup(void)
* Description:   
*
* Param:   none
* Return:  none
* Author:  
******************************************************************************/
void CanTrans_Wakeup( void )
{
    CanTrans_ColdInit();
}

/*****************************************************************************/
/**
* Function Name: UINT8 CanTrans_TxMsg(Uds_TxDesc_S *tx_msg_desc)
* Description:   
*
* Param:   Uds_TxDesc_S *tx_msg_desc
* Return:  TRUE/FALSE
* Author:  
******************************************************************************/
UINT8 CanTrans_TxMsg( Uds_TxDesc_S *tx_msg_desc )
{
    if ((s_cantp_sts & COMM_STATUS_MASK) != TX_RX_IDLE)
    {
        return(0);
    }

    /*
    ** Set the TX_IN_PROGRESS bit,it will be cleared when TX is done.
    */
    SETBIT(s_cantp_sts, TX_IN_PROGRESS);

    CLEARBIT(s_cantp_sts, TX_LAST_FRAME_ERROR);   
    /*
    ** Assign fields in the control structure to initiate TX,
    ** then TX the appropriate frame type.
    */
    s_cantp_tx_info.next_tx_byte = 1;
    s_cantp_tx_info.msg_length   = tx_msg_desc->msg_length;
    s_cantp_tx_info.ptr1         = tx_msg_desc->ptr1;
    s_cantp_tx_info.length1      = tx_msg_desc->length1;
    s_cantp_tx_info.ptr2         = tx_msg_desc->ptr2;
    s_cantp_tx_info.length2      = tx_msg_desc->length2;

    if (s_cantp_tx_info.msg_length <= SF_DL_MAX_BYTES)
    {
        CanTrans_TxFrame(TX_SF);
    }
    else
    {
        CanTrans_TxFrame(TX_FF);
    }

    return(1);
}

/****************************************************************************/
/**
 * Function Name: CanTrans_Rx
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
void CanTrans_Rx( UINT8 *rx_buffer_ptr, UINT8 rxLen, Uds_DiagAddrMode_E mode )
{
    if (g_cantp_rx_enable && s_cantp_rx_frame.tpci == 0 && rxLen == 8 
//     && lin1_bool_rd(CX62_PEPS_LIN1_RX_SlaveBootLoaderEnable_l_signal_bool_Handle)
     )
    {
        if (rx_buffer_ptr[0] == 0x02
            && rx_buffer_ptr[1] == 0x3E
            && rx_buffer_ptr[2] == 0x80
            )
        {
            SETBIT(g_uds_diag_status, KEEPING_DIAG);
        }
        else
        {
            (void)memcpy(&s_cantp_rx_frame.tpci, rx_buffer_ptr, 8);
            g_diag_can_address_mode = mode;
        }
    }
}

/****************************************************************************/
/**
 * Function Name: CanTrans_Manage
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
void CanTrans_Manage( void )
{	
    /*
    ** If new message has been received, process it.
    */
     
    if (s_cantp_rx_frame.tpci != 0)
    {
        CanTrans_RxStateAnalyse();
        /*clear first rx frame byte to check a new frame next time*/
        s_cantp_rx_frame.tpci = 0;
    }

    if( (TESTBIT(s_cantp_sts,TX_IN_PROGRESS)) 
     && (!TESTBIT(s_cantp_sts,TX_WAIT_FC))
      )
    {
        /* CanTrans_TxFrame(TX_CF); */
    #if (SEND_CF_FRAME_TYPE == SEND_CF_FRAME_UNINTERRUPTED)
        while( (TESTBIT(s_cantp_sts,TX_IN_PROGRESS)) 
            && (!TESTBIT(s_cantp_sts,TX_WAIT_FC))
             )
        {
    #endif        
       	    if( 0x00 == s_u8_block_size )
	        {
                /* st_min time, received from tester*/
		        if( 0x00 == s_u8_cf_stmin_time ) 
		        {
            		CanTrans_TxFrame(TX_CF);
		        }
		        else
		        {
            		/* st_min time, received from tester is not 0 */
			        if( 0x00 == s_u8_cf_stmin_wait_time )
			        {
				        CanTrans_TxFrame(TX_CF);
                		s_u8_cf_stmin_wait_time = s_u8_cf_stmin_time;
			        }
		        }
	        }
	        else if( s_u8_block_size > 1 )
	        {
		        if( 0x00 == s_u8_cf_stmin_time )
		        {
                    CanTrans_TxFrame(TX_CF);
                    if( !TESTBIT(s_cantp_sts, TX_LAST_FRAME_ERROR) )
                    {
                        s_u8_block_size--;
                    }              
                #if (SEND_CF_FRAME_TYPE == SEND_CF_FRAME_UNINTERRUPTED)
                    else
                    {
                        break;  
                    }
                #endif
		        }
		        else
		        {
			        if( 0x00 == s_u8_cf_stmin_wait_time )
			        {
				        CanTrans_TxFrame(TX_CF);
                        if( !TESTBIT(s_cantp_sts, TX_LAST_FRAME_ERROR) )
                        {
                            s_u8_block_size--;
                        }                
                    #if (SEND_CF_FRAME_TYPE == SEND_CF_FRAME_UNINTERRUPTED)
                        else
                        { 
                            break;  
                        }
                    #endif
            
                        /* start stmin time,interval of consecutive frame */
                        s_u8_cf_stmin_wait_time = s_u8_cf_stmin_time;
			        }
		        }

		        if( s_u8_block_size <= 1 )
		        {
                    SETBIT(s_cantp_sts, TX_WAIT_FC);
                
                    /* start flow control wait timer */
                    s_u8_fc_wait_time = FC_WAIT_TIMEOUT;     
		        }
	        }
    #if (SEND_CF_FRAME_TYPE == SEND_CF_FRAME_UNINTERRUPTED)
        } 
    #endif
    
    }
    else if (TESTBIT(s_cantp_sts, TX_FC_TPDU))
    {
        CanTrans_TxFrame(TX_FC);
        CLEARBIT(s_cantp_sts, TX_FC_TPDU);
				
        /*start to counter the CF wait time*/
        s_u8_cf_wait_time = CF_WAIT_TIMEOUT;   
    }

    if( (TESTBIT(s_cantp_sts, TX_IN_PROGRESS)) 
     && (TESTBIT(s_cantp_sts, TX_WAIT_FC))
      )
    {
        /* wait for flow control frame time out! */
        if (s_u8_fc_wait_time == 0)
        {
            CLEARBIT(s_cantp_sts, (TX_IN_PROGRESS | TX_WAIT_FC | TX_LAST_FRAME_ERROR));
        }
    }

    if( (TESTBIT(s_cantp_sts, RX_IN_PROGRESS))
     && (!TESTBIT(s_cantp_sts, TX_FC_TPDU))
      )
    {
        if( 0x00 == s_u8_cf_wait_time )
        {      	
            SETBIT(g_cantp_rx_buffer.info_byte,TX_ABORTED); 
            /*
            ** wait for consecutive frame Time out,abort Rx.
            */
            CLEARBIT(s_cantp_sts, RX_IN_PROGRESS);
            /* 
            ** When Time out occurs, ECU has to send negative
            ** resp(71) for the first frame.First frame is already copied in to
            ** g_cantp_rx_buffer.msg buffer but message length is not yet copied.
            ** So assign data length as First Frame length and set RX_MSG_RCVD
            ** flag.This flag indicates to a new message has come.
            */              
            g_cantp_rx_buffer.msg_length= (SF_DL_MAX_BYTES-1);
            SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_RCVD);
        }
    }
}

/****************************************************************************/
/**
 * Function Name: CanTrans_TxFrame
 * Description: tx a frame
 *              if last frame was sent unsuccessfully,set TX_LAST_FRAME_ERROR
 *              falg,freeze last frame buffer. It would be sent on next time.
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
static void CanTrans_TxFrame( Uds_FrameType_E frame_type )
{
    static Uds_TxFrameData_S s_cantp_tx_frame;

    UINT16 u16_data_bytes_to_tx = 0x00;
    UINT8 * p_u8_tx_frame_ptr = NULL_PTR;

    ///////////////////////////////////

    if( !TESTBIT(s_cantp_sts, TX_LAST_FRAME_ERROR) )  
    { 
        s_cantp_tx_frame.data1 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data2 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data3 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data4 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data5 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data6 = (UINT8)TX_FRAME_DATA_INIT_VALUE;
        s_cantp_tx_frame.data7 = (UINT8)TX_FRAME_DATA_INIT_VALUE;

        /*
        ** Place control bytes into the frame.
        */
        switch (frame_type)
        {
        case  TX_SF: /* single frame */
              s_cantp_tx_frame.tpci = SF_TPDU | (UINT8)(s_cantp_tx_info.msg_length);
              u16_data_bytes_to_tx  = s_cantp_tx_info.msg_length;
              p_u8_tx_frame_ptr     = &s_cantp_tx_frame.data1;
              break;

        case  TX_FF:/* first frame */
              s_cantp_tx_frame.tpci = FF_TPDU | (UINT8)((s_cantp_tx_info.msg_length>>8) & 0x0F);
              s_cantp_tx_frame.DL   = (UINT8)(s_cantp_tx_info.msg_length & 0xFF);
              u16_data_bytes_to_tx  = SF_DL_MAX_BYTES - 1; /* 6 bytes */
              p_u8_tx_frame_ptr     = &s_cantp_tx_frame.data2;
              s_cantp_tx_info.next_sequence_num = BEGINNING_SEQ_NUMBER;
	          s_b_fc_wait_timeout_disable = FALSE;
              break;

        case  TX_CF: /* Conscutive Frame */
              s_cantp_tx_frame.tpci = CF_TPDU | s_cantp_tx_info.next_sequence_num;
              s_cantp_tx_info.next_sequence_num = (UINT8)(s_cantp_tx_info.next_sequence_num + (UINT8)1) % (CF_SN_MAX_VALUE + (UINT8)1);  
                                                                
              /*
              ** Compute bytes to Tx in this frame, clamping at SF_DL_MAX_BYTES.
              */
              u16_data_bytes_to_tx = (s_cantp_tx_info.msg_length - s_cantp_tx_info.next_tx_byte) + (UINT8) 1;
                                 
              if (u16_data_bytes_to_tx > SF_DL_MAX_BYTES)
              {
                  u16_data_bytes_to_tx = SF_DL_MAX_BYTES;
              }
              p_u8_tx_frame_ptr = &s_cantp_tx_frame.data1;
          
              break;

        case  TX_FC:
              if(s_b_over_flow_flag == TRUE)
              {
                  s_cantp_tx_frame.tpci = FC_OVFL_PDU;
              }
              else
              {
                  s_cantp_tx_frame.tpci = FC_TPDU;
              }
              s_cantp_tx_frame.BS   = FC_BS_MAX_VALUE; 
              s_cantp_tx_frame.ST   = FC_ST_MIN_VALUE;
              u16_data_bytes_to_tx  = 0;
              s_u8_cantp_rx_block = 0;
              break;

        default:
              return;
        }

        /*
        ** Place data bytes into the frame.
        */
        while( u16_data_bytes_to_tx != 0 )
        {
            if (s_cantp_tx_info.next_tx_byte > s_cantp_tx_info.length1)
            {
                *p_u8_tx_frame_ptr = *s_cantp_tx_info.ptr2;
                ++s_cantp_tx_info.ptr2;
            }
            else
            {
                *p_u8_tx_frame_ptr = *s_cantp_tx_info.ptr1;
                ++s_cantp_tx_info.ptr1;
            }
            --u16_data_bytes_to_tx;
            ++s_cantp_tx_info.next_tx_byte;
            ++p_u8_tx_frame_ptr;
        }    
    }
    
    if( TRUE == UdsCallback_SendFrame(c_u32_can_tx_diag_id, &s_cantp_tx_frame.tpci, 8) )
    {
		CLEARBIT(s_cantp_sts, TX_LAST_FRAME_ERROR);	
        s_cantp_rx_frame.tpci =0;
        /*
        ** Verify if the data has been completely transfered. If not, set flag to
        ** transfer CF frames. (For FC frames, s_cantp_tx_info is not used and there
        ** should not be a CF frame after a FC frame.)
        */
        if ( (s_cantp_tx_info.msg_length >= s_cantp_tx_info.next_tx_byte)
          && (frame_type != TX_FC) 
           )
        {
            SETBIT(s_cantp_sts, TX_IN_PROGRESS);

            if (frame_type == TX_FF)
            {
                SETBIT(s_cantp_sts, TX_WAIT_FC);                
                s_u8_fc_wait_time = FC_WAIT_TIMEOUT; /* start flow control wait timer */
            }
        }
        else
        {
            CLEARBIT(s_cantp_sts, TX_IN_PROGRESS);
        } 
    }
    else
    {
        /* user specific action incase transmission request is not successful */
        SETBIT(s_cantp_sts, TX_LAST_FRAME_ERROR);
    }
}

/****************************************************************************/
/**
 * Function Name: CanTrans_RxStateAnalyse
 * Description: none
 *
 * Param:   none
 * Return:  none
 * Author:  2015/05/05, hui.pang create this function
 ****************************************************************************/
static void CanTrans_RxStateAnalyse( void )
{	  
    static Uds_PCI_E s_diag_flow_control_sts = FC_STATUS_CONTINUE;
    /*
    ** Temporary data length variable.
    */
    static UINT16 s_u16_cantp_data_length = 0x00;
    static Uds_RxInfo_S s_cantp_rx_info;
    
    UINT16 u16_data_length = 0x00;

    
   

   /*   The reason for not allowing response in CF_TPDU and FC_TPDU 
   **   insert in DIAG_FUNCTION_ADDR_MODE  <<lele>>
   */
    if(		(((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == CF_TPDU)
             	 ||((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == FC_TPDU))
            && (g_diag_can_address_mode == DIAG_FUNCTION_ADDR_MODE )
       )
    {
        return;
    }
   
    /////////////////////////////////////

    /*
    ** The reason for not allowing RX while TX is in progress is to prevent
    ** any possibility that a TX buffer gets over written by processing a new
    ** request message before TX is complete.
    */
    if(g_cantp_rx_buffer.info_byte != 0)
    {
        return;
    }
    /* As per 15765-2 network layer spec when Tx is in progress, if SF,FF,CF
      comes just ignore it */ 
    if( (TESTBIT(s_cantp_sts, TX_IN_PROGRESS)) 
     && ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) != FC_TPDU)
      )
    {
        return;      
    }

    /*
    ** In case of $78 response handling, don't need to receive diag message
    ** into diag buffer. just inform to Application layer that new msg has
    ** come for diag timer reset.
    */
    if(TESTBIT(g_uds_diag_status, NEGRESP78_PROCESSING) != 0)
    {
        if(TESTBIT(g_uds_diag_status, NEGRESP78_WAIT_60SEC) != 0)
        {    
            if( ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == SF_TPDU) 
             || ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == FF_TPDU) 
              )
            {
                CLEARBIT( s_cantp_sts, (TX_IN_PROGRESS|TX_WAIT_FC|RX_IN_PROGRESS|TX_LAST_FRAME_ERROR));
                SETBIT( g_cantp_rx_buffer.info_byte, RX_MSG_RCVD );

                return;
            }
        }
        else
        {
            /* 
            ** Diag Msg received after $78 resp time out time, so 
            ** clear NEGRESP78_PROCESSING flag to process this msg.
            */
            CLEARBIT( g_uds_diag_status, NEGRESP78_PROCESSING );
        }
    }

    /* single frame */
    if ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == SF_TPDU) 
    {
        /* As per 15765-2 network layer spec when SF_DL is 0 or greater
        ** than 7, just ignore it.
        */ 
        u16_data_length = (s_cantp_rx_frame.tpci & SF_DL_MASK_LONG);

        if( (u16_data_length == 0) 
         || (u16_data_length > SF_DL_MAX_BYTES)
          )
        {
            CLEARBIT(s_cantp_sts, (TX_IN_PROGRESS | TX_WAIT_FC | RX_IN_PROGRESS | TX_LAST_FRAME_ERROR));
            return;					
        }
        g_cantp_rx_buffer.msg_length =  u16_data_length;
        /*
       	** Copy the frame to the RX buffer. Clear the RX_IN_PROGRESS bit
       	** (SF frame) will abort multi-frame transfer.
       	*/
       	(void)memcpy(&g_cantp_rx_buffer.msg[0], &s_cantp_rx_frame.data1,
                    (s_cantp_rx_frame.tpci & SF_DL_MASK));

        CLEARBIT(s_cantp_sts, (TX_IN_PROGRESS | TX_WAIT_FC | RX_IN_PROGRESS |TX_LAST_FRAME_ERROR));
        SETBIT(g_cantp_rx_buffer.info_byte, RX_MSG_RCVD);
    }
    /* first frame */
    else if ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == FF_TPDU)
    {
        u16_data_length = ((UINT16)(s_cantp_rx_frame.tpci & FF_EX_DL_MASK) << 8) 
                                 + s_cantp_rx_frame.DL;
        s_b_fc_wait_timeout_disable = FALSE;
        s_u16_cantp_data_length = u16_data_length;
        /*
        ** Check for invalid conditions (if any of these are found, just abort RX).
        ** (1) Message length longer than RX buffer.
        ** (2) Message length less than or equal to number bytes per SF. 
        ** (3) XDL is not 0.
        */
        if (u16_data_length <= SF_DL_MAX_BYTES)
        {
            SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_INVL_TPCI);

            CLEARBIT(s_cantp_sts, (RX_IN_PROGRESS));

            g_cantp_rx_buffer.msg_length = u16_data_length;
            (void)memcpy(&g_cantp_rx_buffer.msg[0], &s_cantp_rx_frame.data2, (SF_DL_MAX_BYTES-1));
            SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_RCVD);
            return;
        }

        if (u16_data_length > RX_MAX_TP_BYTES)
        {
            /*
            ** Clear the RX_IN_PROGRESS bit (will abort in-progress multi-frame
            ** transfers).
            */
            /*CLEARBIT(cantpe_status, RX_IN_PROGRESS);
            return;*/
            /*
            ** As per 15765-2 Network layer spec if Rx data length is
            ** greater diag buffer length receive datas upto diag_buffer
            ** length.Skip remaining datas.Application layer will send
            ** appropriate negative response to that request message.
            */
            u16_data_length = RX_MAX_TP_BYTES;
            s_b_over_flow_flag = TRUE;
        }
        else
        {
            s_b_over_flow_flag = FALSE;
        }

        /*
        ** Clear the RX buffer, copy first frame to RX buffer and initiate RX.
        */
        (void)memcpy(&g_cantp_rx_buffer.msg[0], &s_cantp_rx_frame.data2, (SF_DL_MAX_BYTES-1));
        s_cantp_rx_info.next_sequence_num = BEGINNING_SEQ_NUMBER;
        s_cantp_rx_info.next_rx_offset    = (SF_DL_MAX_BYTES-1);
        s_cantp_rx_info.bytes_left_to_rx  = u16_data_length - (SF_DL_MAX_BYTES-1);
				
        CLEARBIT(s_cantp_sts, (TX_IN_PROGRESS | TX_WAIT_FC));
        SETBIT(s_cantp_sts, RX_IN_PROGRESS);
				
        /* set flag to send flow control frame */
        if(g_diag_can_address_mode == DIAG_PHYSIC_ADDR_MODE) // RQ, 20131203, we only send FC when get the command from the physic ID
	    {
        	SETBIT(s_cantp_sts, TX_FC_TPDU);
        }
    }
    /* Consecutive Frame */
    else if( ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == CF_TPDU)
        /* Don't accept consecutive frame until flow control frame sent by ECU */
             && (!TESTBIT(s_cantp_sts, TX_FC_TPDU)) 
        /* Don't accept consecutive frame if we are sending CF*/
             && (!TESTBIT(s_cantp_sts, TX_IN_PROGRESS)))
    {
        /*
        ** Ignore frame unless RX in progress.
        */
        if (TESTBIT(s_cantp_sts, RX_IN_PROGRESS))
        {
            /*
            ** Verify the sequence number is as expected.
            */
            if ((s_cantp_rx_frame.tpci & CF_SN_MASK) == s_cantp_rx_info.next_sequence_num)
            {
                /*
                **  Last frame in message?
                */                
                if (s_cantp_rx_info.bytes_left_to_rx <= SF_DL_MAX_BYTES)
                {
                    (void)memcpy(&g_cantp_rx_buffer.msg[ s_cantp_rx_info.next_rx_offset ],
                           &s_cantp_rx_frame.data1, s_cantp_rx_info.bytes_left_to_rx);
                    g_cantp_rx_buffer.msg_length = s_cantp_rx_info.next_rx_offset +
                                                s_cantp_rx_info.bytes_left_to_rx;

                    CLEARBIT(s_cantp_sts, RX_IN_PROGRESS);
                    SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_RCVD);
										
                    if(s_u16_cantp_data_length > RX_MAX_TP_BYTES)
                    {
                        SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_INVL_LEN);
                    }
                }
                else
                {
                    /*
                    ** not the last frame,copy bytes to RX buffer and
                    ** continue RXing.
                    */
                    (void)memcpy( &g_cantp_rx_buffer.msg[ s_cantp_rx_info.next_rx_offset ],
                                  &s_cantp_rx_frame.data1, 
                                  SF_DL_MAX_BYTES );
                    s_cantp_rx_info.next_sequence_num = (UINT8)((s_cantp_rx_info.next_sequence_num+1) % (CF_SN_MAX_VALUE+1));
                    s_cantp_rx_info.bytes_left_to_rx  -= SF_DL_MAX_BYTES;
                    s_cantp_rx_info.next_rx_offset    += SF_DL_MAX_BYTES;
                    s_u8_cf_wait_time = CF_WAIT_TIMEOUT;
                    
                    if(FC_BS_MAX_VALUE != 0
                    	&&++s_u8_cantp_rx_block >= FC_BS_MAX_VALUE)
                    {
                    	SETBIT(s_cantp_sts, TX_FC_TPDU);
                    }
                }
            }
            else
            {
                /*
                ** Invalid sequence number...abort Rx.As a diagnostic measure, 
                ** consideration was given to send an FC frame here, but not done.
                */
                CLEARBIT(s_cantp_sts, RX_IN_PROGRESS);
                /* 
                ** When Invalid sequence number is received, ECU has to send 
                ** negative resp for the first frame.so set RX_MSG_RCVD flag.
                ** This flag indicates to DiagManager as new message has come.
                */   
                SETBIT(g_cantp_rx_buffer.info_byte,TX_ABORTED);    // RQ, 20120416, 
                g_cantp_rx_buffer.msg_length = (SF_DL_MAX_BYTES-1);
                SETBIT(g_cantp_rx_buffer.info_byte,RX_MSG_RCVD);
            }
        }
    }
    /* flow control frame */
    else if ((s_cantp_rx_frame.tpci & FRAME_TYPE_MASK) == FC_TPDU)
    {
    	if( 0x00 == TESTBIT(s_cantp_sts, TX_WAIT_FC) )
    	{
		    /* do nothing */
    	}
    	/* we only clear the CF when get the CF from the physic ID */
//    	else if( g_diag_can_address_mode == DIAG_PHYSIC_ADDR_MODE )
        else
        {		
	        /*
	        ** Receive Flow Status(FS) for Transmiting the CF Frames.
	        ** The value of FS shall be set to zero that means that the
	        ** tester is ready to receive a maximum number of CF.
	        */
	        s_diag_flow_control_sts = FC_STATUS_CONTINUE;
	        if( (s_cantp_rx_frame.tpci & FC_STATUS_MASK) != 0x00 )
	        {
	            /* Flow Status(FS)
	            ** 0: Continue to send(CTS)
	            ** 1: wait(WT)
	            ** 2: Overflow(OVFLW)
	            */

	            // RQ, add 20131204, we use flow statusE2
	            s_diag_flow_control_sts = s_cantp_rx_frame.tpci & FC_STATUS_MASK;
	            				      
	        }
	        /*
	        ** Receive the BS and ST min time for Transmiting the CF Frames.
	        */

	        if( 0x00 != s_cantp_rx_frame.data1 ) /* BS */
	        {
	            s_u8_block_size = s_cantp_rx_frame.data1 + 1;
	        }
	        else
	        {
	            s_u8_block_size = 0x00;
	        }

	        if( 0x00 != (s_cantp_rx_frame.data2 & 0x7F) ) /* ST */
	        {
	            /* 
	            ** Valid Range for STMin timeout is 0 - 127ms. 
	            */
	            s_u8_cf_stmin_time = (s_cantp_rx_frame.data2 & 0x7F) + 5;   /* extend the delay time */  
	        }
	        else
	        {
	            s_u8_cf_stmin_time = 0x00;
	        }

	        if( (s_diag_flow_control_sts == FC_STATUS_CONTINUE) 
	         && (FALSE == s_b_fc_wait_timeout_disable)
	          )
	        {
		        CLEARBIT(s_cantp_sts, TX_WAIT_FC);
			    s_u8_fc_wait_time = 0;
		    }
		    else if(s_diag_flow_control_sts == FC_STATUS_WAIT)
		    {
			    s_u8_fc_wait_time = FC_WAIT_TIMEOUT;  /* if wait, we will wait another time */
		    }
		    else if(s_diag_flow_control_sts == FC_STATUS_OVERFLOW)  
		    {
			    /* do nothing here, if over flow, we will stop sending 
			       any message until we got new cmd */
			    s_u8_fc_wait_time = 1;   /* exit after 10ms */
		    }
		    else
		    {
			    /* do nothing here, if over flow, we will stop sending 
			       any message until we got new cmd */
			    s_u8_fc_wait_time = 1;   /* exit after 10ms */
		    }
        }
//        else if( g_diag_can_address_mode == DIAG_FUNCTION_ADDR_MODE )
//        {
//            /* do nothing */
//        }
//        else
//        {
//            /* do nothing */
//        }
    }
//    else
//    {
//        /* do nothing */
//    }
}

#pragma CODE_SEG  DEFAULT

/*****************************************************************************
** End File
*****************************************************************************/
